package cn.cjx.basic.service.impl;

import cn.cjx.basic.constant.BaseConstant;
import cn.cjx.basic.dto.RegisterDto;
import cn.cjx.basic.exception.BusinessException;
import cn.cjx.basic.service.IVerifyCodeService;
import cn.cjx.basic.utils.StrUtils;
import cn.cjx.basic.utils.VerifyCodeUtils;
import cn.cjx.user.domain.User;
import cn.cjx.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * 业务流程
 * 1.生成验证码
 * 2.保存验证码到redis，设置一个过期时间
 * 3.使用JDK的2D引擎对验证码进行渲染，得到图形验证码
 * 4.使用base64位的编码引擎，把图形验证码编码成字符串
 * 5.将字符串返回给前端
 *
 * @author: cjx
 * @Date: 2022/5/8
 */
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private UserMapper userMapper;


	@Override
	public String imageCode(String key) {

		//1.生成验证码
		String code = StrUtils.getComplexRandomString(5);
		//2.保存验证码到redis，设置一个过期时间
		redisTemplate.opsForValue().set(key, code, 3, TimeUnit.MINUTES);
		//3.使用JDK的2D引擎对验证码进行渲染，得到图形验证码
		//4.使用base64位的编码引擎，把图形验证码编码成字符串
		return VerifyCodeUtils.VerifyCode(115, 48, code);
	}

	@Override
	public void sendMsgCode(RegisterDto dto) {
		String phone = dto.getPhone();
		String type = dto.getType();
		if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(type)) {
			throw new BusinessException("参数不能为空");
		}
		if (type.equals("register")) {
			//业务键是register即为注册，此时调用发送注册验证码的方法
			registerSmsCode(dto);
		} else if (type.equals("binder")) {
			//业务键是binder即为绑定微信账号，此时调用发送绑定验证码的方法
			binderSmsCode(phone);
		}
	}

	/**
	 * @author 陈吉祥
	 * @Date 2022/5/12
	 * 真正的发送短信的方法
	 */
	private void sendSmsCode(String businessKey) {
		//从redis中获取key
		String smsCodeKey = businessKey;//拼接手机号
		Object keyTemp = redisTemplate.opsForValue().get(smsCodeKey); //从redis获取key
		String smsCode = "";//定义一个空的验证码前缀
		if (keyTemp != null) {
			Long oldTime = Long.valueOf(keyTemp.toString().split(":")[1]);
			//如果验证码已获取时间的时间小于一分钟，他在故意刷新，或者跳过前端直接调你接口
			if (System.currentTimeMillis() - oldTime <= 1 * 60 * 1000) {
				throw new BusinessException("你搁着搁着呢？");
			}
			//时间大于1分钟，则使用原来的验证码
			smsCode = keyTemp.toString().split(":")[0];
		} else {
			smsCode = StrUtils.getComplexRandomString(5);
		}
		//设置过期时间
		String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
		//保存到数据库
		redisTemplate.opsForValue().set(smsCodeKey, smsCodeValue, 3, TimeUnit.MINUTES);
//		//发送短信验证码
//		SendMsgUtil.sendMsg("17313227886","您的验证码是" + smsCode + "请尽快使用");

		System.out.println("你的验证码是" + smsCode + "请尽快使用");
	}

	/**
	 * @author 陈吉祥
	 * @Date 2022/5/12
	 * 绑定账号发送的验证码
	 */
	private void binderSmsCode(String phone) {
		String businessKey = BaseConstant.VerifyCodeConstant.BUSINESS_BINDER_PREFIX + phone;//拼接手机号
		sendSmsCode(businessKey);
	}

	/**
	 * @author 陈吉祥
	 * @Date 2022/5/12
	 * 注册账号发送的验证码
	 */
	private void registerSmsCode(RegisterDto dto) {
		String phone = dto.getPhone();
		String imageCodeValue = dto.getImageCodeValue();
		String imageCodeKey = dto.getImageCodeKey();

		//空校验
		if (!StringUtils.hasLength(phone)) {
			throw new BusinessException("手机号不可为空");
		}
		if (!StringUtils.hasLength(imageCodeKey)) {
			throw new BusinessException("请刷新页面重新获取图片验证码");
		}
		if (!StringUtils.hasLength(imageCodeValue)) {
			throw new BusinessException("图片验证码不可以为空");
		}

		//校验图形验证码
		//根据前端传入的Key去redis获取验证码
		Object imageCodeVal = redisTemplate.opsForValue().get(imageCodeKey);
		//后端没有查到该验证码
		if (imageCodeVal == null) {
			throw new BusinessException("无效或过期的图形验证码，请重新获取");
		}
		//后端查到了去和redis中的值作比较
		if (!imageCodeVal.toString().equalsIgnoreCase(imageCodeValue)) {
			throw new BusinessException("错误的图形验证码，请输入正确的图形验证码");
		}
		User userTmp = userMapper.loadByPhone(phone);
		if (userTmp != null) {
//        如果被注册，报错：用户已存在，请直接登录！！
			throw new BusinessException("用户已存在，请直接登录！！");
		}
		String businessKey = BaseConstant.VerifyCodeConstant.BUSINESS_REGISTER_PREFIX + phone;//拼接手机号
		sendSmsCode(businessKey);
	}


}

